package com.pearlsoft.webapp.core.web.controller;

import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.pearlsoft.webapp.core.executor.Executor;
import com.pearlsoft.webapp.core.web.util.HttpUtil;

/**
 * 
 * BaseController
 * 
 * @Creator haitingr
 * @Create-DateTime 2011-10-19
 */
@Controller
public class MainController extends MultiActionController {

	protected static Log logger = LogFactory.getLog(MainController.class);

	protected String _json_message = "_json_message";

	protected String dataset_executor = "dataset_executor";

	protected String query_executor = "query_executor";

	protected ThreadLocal<HttpServletRequest> current_request = new ThreadLocal<HttpServletRequest>();

	protected ThreadLocal<HttpServletResponse> current_response = new ThreadLocal<HttpServletResponse>();

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			current_request.set(request);
			current_response.set(response);
			return super.handleRequest(request, response);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			request.setAttribute("_exception_", e);
			return new ModelAndView("_exception_print");
		} finally {
			current_request.set(null);
			current_response.set(null);
		}
	}

	@RequestMapping("/query.asp")
	public ModelAndView query(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String json = request.getParameter(_json_message);
		logger.debug("controller for query invoked,json message:[" + json + "]");
		Executor executor = this.getBean(query_executor, Executor.class);
		current_request.set(request);
		current_response.set(response);
		byte[] values = execute(executor, json);
		current_request.set(null);
		current_response.set(null);
		response.setContentType("text/plain");
		response.getOutputStream().write(values);
		response.getOutputStream().flush();
		return null;
	}

	@RequestMapping("/dataset.asp")
	public ModelAndView dataset(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String json = request.getParameter(_json_message);
		logger.debug("controller for dataset invoked,json message:[" + json + "]");
		Executor executor = this.getBean(dataset_executor, Executor.class);
		current_request.set(request);
		current_response.set(response);
		byte[] values = execute(executor, json);
		current_request.set(null);
		current_response.set(null);
		response.setContentType("text/plain");
		response.getOutputStream().write(values);
		response.getOutputStream().flush();
		return null;
	}

	protected byte[] execute(Executor executor, String json) throws Exception {
		try {
			executor.setHttpServletRequest(current_request.get());
			executor.setHttpServletResponse(current_response.get());
			byte[] values = executor.execute(json.getBytes("UTF-8"));
			return values;
		}catch(Exception e){
			e.printStackTrace();
		} finally {
			executor.setHttpServletRequest(null);
			executor.setHttpServletResponse(null);
		}
		return null;
	}

	/**
	 * find object from spring context
	 * 
	 * @param name
	 * @return
	 */
	protected Object getBean(String name) {
		return this.getApplicationContext().getBean(name);
	}

	/**
	 * find Object typed T from spring context
	 * 
	 * @param <T>
	 * @param name
	 * @param cls
	 * @return
	 */
	protected <T> T getBean(String name, Class<? extends T> cls) {
		return this.getApplicationContext().getBean(name, cls);
	}

	/**
	 * 
	 * @param request
	 * @param key
	 * @return
	 */
	protected String getParameter(String key) {
		return current_request.get().getParameter(key);
	}

	/**
	 * 
	 * @param request
	 * @param key
	 * @return
	 */
	protected Integer getParameterAsInteger(String key) {
		String value = this.getParameter(key);
		return Integer.parseInt(value);
	}

	/**
	 * 
	 * @param key
	 * @param value
	 */
	protected void setAttribute(String key, Object value) {
		current_request.get().setAttribute(key, value);
	}

	/**
	 * 
	 * @param request
	 * @param values
	 */
	protected void setAttributes(Map<String, Object> values) {
		for (String key : values.keySet()) {
			current_request.get().setAttribute(key, values.get(key));
		}
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	protected HttpSession getSession() {
		return HttpUtil.getSession(current_request.get());
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	protected String getCookieValue(String name) {
		Cookie[] cookies = current_request.get().getCookies();
		for (int i = 0; i < cookies.length; i++) {
			if (cookies[i].getName().equals(name)) {
				return cookies[i].getValue();
			}
		}
		return "";
	}

	/**
	 * 
	 * @param name
	 * @param value
	 */
	protected void setCookie(String name, String value, String domain, int maxAge, String path, boolean secured) {
		Cookie cookie = new Cookie(name, value);
		cookie.setDomain(domain);
		cookie.setMaxAge(maxAge);
		cookie.setPath(path);
		cookie.setSecure(secured);
		this.current_response.get().addCookie(cookie);
	}

	/**
	 * 
	 * @param name
	 * @param value
	 * @param secured
	 */
	protected void setCookie(String name, String value, boolean secured) {
		setCookie(name, value, "", -1, "/", secured);
	}

	/**
	 * 
	 * @param name
	 * @param value
	 * @param maxAge
	 */
	protected void setCookie(String name, String value, int maxAge) {
		setCookie(name, value, "", maxAge, "/", false);
	}

	/**
	 * 
	 * @param name
	 * @param value
	 * @param domain
	 */
	protected void setCookie(String name, String value, String domain) {
		setCookie(name, value, domain, -1, "/", false);
	}

}
